package com.ruicar.afs.cloud.afscase.autoaudit.util;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkTaskPool;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.LoanServiceBox;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.StepInvoker;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.StepParam;
import com.ruicar.afs.cloud.afscase.autoaudit.loan.Steps;
import com.ruicar.afs.cloud.afscase.common.utils.Const;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.CaseContractInfo;
import com.ruicar.afs.cloud.afscase.infomanagement.service.CaseContractInfoService;
import com.ruicar.afs.cloud.afscase.loanactivatepool.entity.LoanActivatePool;
import com.ruicar.afs.cloud.afscase.loanapprove.condition.LoanApproveCondition;
import com.ruicar.afs.cloud.afscase.processor.enums.LoanSubmitEnum;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.risk.api.enums.tortoise.GwtTortoiseAntiFraudCallStep;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import java.util.*;

/**
 * @Description
 * @Author fangchenliang
 * @Date
 */

@UtilityClass
@Slf4j
public class ActiveStepUtil {

    final LoanServiceBox serviceBox;

    static {
        serviceBox = SpringContextHolder.getBean(LoanServiceBox.class);
    }

    /**
     * @Description 激活步骤：超期判断-额度判断-放款审核通过-黑名单-审批时效率
     * @Author fangchenliang
     * @Date
     */
    public void prevSteps(StepParam stepParams) {
        Assert.isTrue(StringUtils.isNotBlank(stepParams.getContractNo()),"请选择至少一个合同激活!");
        LoanActivatePool loanActivatePool=serviceBox.getLoanActivateService().getOne(Wrappers.<LoanActivatePool>lambdaQuery()
                .eq(LoanActivatePool::getContractNo,stepParams.getContractNo()));
        Assert.isTrue(ObjectUtils.isNotEmpty(loanActivatePool),"未查找到+"+stepParams.getContractNo()+"合同！");
        CaseContractInfoService caseContractInfoService = serviceBox.getCaseContractInfoService();
        stepParams.setLoanActivatePool(loanActivatePool);
        if (Objects.isNull(stepParams.getContractInfo())) {
            CaseContractInfo contractInfo = caseContractInfoService.getOne(Wrappers.<CaseContractInfo>lambdaQuery().eq(CaseContractInfo::getContractNo, stepParams.getContractNo()), false);
            stepParams.setContractInfo(contractInfo);
        }
        Steps.create()
                .then(checkOverdue()) // 归档超期
                .then(checkQuota()) //额度
                .then(checkBlackList()) //黑名单
                .then(checkPassLastTime()) //审批时效
                .then(checkGPS()) //GPS审核
                .then(active()) //合同激活
                .err(prevStepErr())
                .end(prevStepEnd())
                .doStep(stepParams, Convert.toInt(stepParams.getLoanActivatePool().getContractActiveSteps(), 0));
    }


    /**
     * 超期判断
     * add by fangchenliang
     */
    private static StepInvoker checkOverdue(){
        return (stepParam, currentStep) ->{
            try {
                if(!serviceBox.getContractActiveProcess().getOverdueStatus(stepParam.getContractNo())){
                    //修改合作激活规则节点到额度判断
                    stepParam.getContractInfo().setActivateRuleNode(LoanActivateRuleNodeEnum.OVERDUE_JUDGEMENT.getState());
                    serviceBox.getCaseContractInfoService().updateById(stepParam.getContractInfo());
                    stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                    serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                    log.info("{}合同超期判断完成",stepParam.getContractNo());
                    return true;
                }else {
                    return false;
                }
            }catch (Exception e){
                log.error("{}超期判断失败：{}",stepParam.getContractNo(),e);
                return false;
            }
        };
    }
    /**
     * 额度判断
     *  add by fangchenliang
     */
    private static StepInvoker checkQuota(){
        return (stepParam, currentStep) ->{
            try{
                if(serviceBox.getContractActiveProcess().quotaOccupy(stepParam.getContractNo())){
                    stepParam.getContractInfo().setActivateRuleNode(LoanActivateRuleNodeEnum.LIMIT_JUDGEMENT.getState());
                    stepParam.getContractInfo().setApplyStatus(ApplyStatusEnum.LOAN_APPROVE_DONE.getState());
                    stepParam.getContractInfo().setLendingPassDate(new Date());
                    log.info("{}放款审核通过修改合同信息表状态{}",stepParam.getContractNo(),ApplyStatusEnum.LOAN_APPROVE_DONE.getState());
                    stepParam.getContractInfo().updateById();
                    stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                    stepParam.getLoanActivatePool().setLoanApproveStatus(ApplyStatusEnum.LOAN_APPROVE_DONE.getState());
                    stepParam.getLoanActivatePool().setLoanApproveTime(new Date());
                    stepParam.getLoanActivatePool().setLimitApproveStatus(WhetherEnum.YES.getCode());
                    stepParam.getLoanActivatePool().setLimitApproveTime(new Date());
                    log.info("{}放款审核通过修改激活池状态{}",stepParam.getContractNo(),ApplyStatusEnum.LOAN_APPROVE_DONE.getState());
                    serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                    log.info("{}放款审核通过之后，入库开票方",stepParam.getContractNo());
                    serviceBox.getCarInvoiceInfoService().saveDrawerParty(stepParam.getContractNo());
                    /**放款审核通过调用玄武*/
                    log.info("{}放款审核通过之后，调用玄武",stepParam.getContractNo());
                    serviceBox.getCaseTortoiseService().safeDelaySignFraudHand(stepParam.getContractInfo().getApplyNo(), GwtTortoiseAntiFraudCallStep.AFTER_LOAN_APPLY_END);
                    //通过MQ推送信息到进件系统
                    serviceBox.getApproveLoanInfoService().sendToApplyNotic(stepParam.getContractNo(),ApplyStatusEnum.LOAN_APPROVE_DONE);
                    return true;
                }else {
                    log.error("{}额度判断失败",stepParam.getContractNo());
                    return false;
                }
            }catch (Exception e){
                log.error("{}额度判断失败：{}",stepParam.getContractNo(),e);
                return false;
            }
        };
    }

    /**
     * 黑名单
     *  add by fangchenliang
     */
    private static StepInvoker checkBlackList(){
        return (stepParam, currentStep) ->{
            if(serviceBox.getCaseConfParamService().checkSwitch(Const.ACTIVE_BLACKLIST_SWITCH)) {
                try {
                    if (serviceBox.getContractActiveProcess().getBlackListHit(stepParam.getContractNo())) {
                        stepParam.getContractInfo().setActivateRuleNode(LoanActivateRuleNodeEnum.BLACKLIST_HIT.getState());
                        serviceBox.getCaseContractInfoService().updateById(stepParam.getContractInfo());
                        stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                        serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                        log.info("{}合同黑名单判断完成",stepParam.getContractNo());
                        return true;
                    } else {
                        return false;
                    }
                } catch (Exception e) {
                    log.error("{}黑名单命中失败：{}", stepParam.getContractNo(), e);
                    return false;
                }
            }else {
                stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                log.info("{}黑名单开关关闭，跳过判断。", stepParam.getContractNo());
                return true;
            }
        };
    }
    /**
     * 审批失效
     *  add by fangchenliang
     */
    private static StepInvoker checkPassLastTime(){
        return (stepParam, currentStep) ->{
            try{
                if(!serviceBox.getContractActiveProcess().getPassLastTime(stepParam.getContractNo())){
                    stepParam.getContractInfo().setActivateRuleNode(LoanActivateRuleNodeEnum.EXECCD_LOAN_PRESCRIPTION.getState());
                    serviceBox.getCaseContractInfoService().updateById(stepParam.getContractInfo());
                    stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                    serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                    log.info("{}合同审批时效判断完成",stepParam.getContractNo());
                    return true;
                }else {
                    log.error("{}案件已超审批时效",stepParam.getContractNo());
                    return false;
                }
            }catch (Exception e){
                log.error("{}审批时效失败：{}",stepParam.getContractNo(),e);
                return false;
            }
        };
    }

    /**
     * 判断GPS
     * @return
     */
    private static StepInvoker checkGPS(){
        return (stepParam, currentStep) ->{
            try{
                /**判断GPS*/
                //暂时取消GPS申请表判断
               /* CarGpsApply carGpsApply=serviceBox.getCarGpsApplyService().getOne(Wrappers.<CarGpsApply>lambdaQuery()
                        .eq(CarGpsApply::getContractNo,stepParam.getContractNo()));*/
                if(stepParam.getLoanActivatePool().getGpsApproveStatus().equals(WhetherEnum.YES.getCode())){
                    stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                    serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                    log.info("{}合同GPS判断完成",stepParam.getContractNo());
                    return true;
                }else{
                    log.error("{}GPS未审核通过",stepParam.getContractNo());
                    return false;
                }
            }catch (Exception e){
                log.error("{}GPS未审核通过：{}",stepParam.getContractNo(),e);
                return false;
            }
        };
    }

    /**
     * 合同激活
     *  add by fangchenliang
     */
    private static StepInvoker active(){
        return (stepParam, currentStep) ->{
            try{
                //通过MQ推送信息到合同系统
                serviceBox.getApproveLoanInfoService().sendLoanMsgToContract(stepParam.getContractNo());
                stepParam.getContractInfo().setActivateRuleNode(LoanActivateRuleNodeEnum.CASE_ACTIVE.getState());
                serviceBox.getCaseContractInfoService().updateById(stepParam.getContractInfo());
                /**修改激活池状态*/
                stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
                serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
                log.info("{}合同激活发送成功",stepParam.getContractNo());
                return true;
            }catch (Exception e){
                log.error("{}激活失败：{}",stepParam.getContractNo(),e);
                return false;
            }
        };
    }

    /**
     * @Description 分单前置错误处理
     * @Author fangchenliang
     * @Date 2020/7/14 17:30
     */
    private static StepInvoker prevStepErr() {
        return (stepParam, currentStep) -> {
            log.info("合同:{}=>执行错误，当前步骤执行至 " + currentStep, stepParam.getContractNo());
            stepParam.getLoanActivatePool().setContractActiveSteps(currentStep);
            serviceBox.getLoanActivateService().updateById(stepParam.getLoanActivatePool());
            return true;
        };
    }
    /**
     * @Description 正常结束处理
     * @Author fangchenliang
     * @Date 2020/7/8 17:31
     */
    private static StepInvoker prevStepEnd() {
        return (stepParam, endStep) -> {
            log.info("{}:自动激活前置逻辑执行完毕，结束工作流开始...", stepParam.getContractNo());
            LoanActivatePool info = stepParam.getLoanActivatePool();
            try {
                if (null != info) {
                    LoanApproveCondition condition = new LoanApproveCondition();
                    condition.setAutoFlag(Boolean.TRUE);
                    condition.setContractNo(info.getContractNo());
                    condition.setApplyNo(info.getApplyNo());
                    condition.setApproveType(ApproveTypeEnum.PROCESS.getValue());
                    condition.setUseScene(UseSceneEnum.GENERAL_LOAN.getValue());
                    condition.setApproveSuggest(AfsEnumUtil.key(LoanSubmitEnum.SUBMIT));
                    condition.setFlowNode(FlowNodeEnum.AUTO.getCode());
                    //工作流流程结束  保存操作记录
                    WorkTaskPool pool = serviceBox.getWorkTaskPoolService().getOne(Wrappers.<WorkTaskPool>lambdaQuery()
                            .eq(WorkTaskPool::getContractNo, info.getContractNo())
                            .eq( WorkTaskPool::getProcessType, condition.getUseScene()), false);
                    if(ObjectUtils.isNotEmpty(pool)) {
                        serviceBox.getLoanWorkflowService().submitWorkflowByScheduleInfo(condition);
                    }
                    info.setContractActiveSteps(endStep);
                    serviceBox.getLoanActivateService().updateById(info);
                }
                log.info("{}:自动激活前置逻辑执行完毕，结束工作流完成...", stepParam.getContractNo());
                return true;
            }catch (Exception e){
                log.error("{}:自动激活前置逻辑执行完毕，结束工作流异常...", stepParam.getContractNo(),e);
                return false;
            }
        };
    }
}
